package com.tfswx.ruleengine.compute.util;

import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

/**
 * @author Ricky
 * @date 2021/4/13
 */
@Slf4j
public class EnumUtil {
    private EnumUtil() {
    }

    public static <E extends Enum<E>> Integer getCode(E parameter) {
        if (parameter == null) {
            return null;
        }
        Class<?> aClass = parameter.getClass();
        try {
            Field code = aClass.getDeclaredField("code");
            code.setAccessible(true);
            return code.getInt(parameter);
        } catch (IllegalAccessException e) {
            log.warn("没有权限获取【code】属性值");
        } catch (NoSuchFieldException e) {
            log.warn("未找到【code】属性");
        }
        return null;
    }

    public static <E> Integer getCode(E parameter) {
        if (parameter == null) {
            return null;
        }
        Class<?> aClass = parameter.getClass();
        try {
            Field code = aClass.getDeclaredField("code");
            code.setAccessible(true);
            return code.getInt(parameter);
        } catch (IllegalAccessException e) {
            log.warn("没有权限获取【code】属性值");
        } catch (NoSuchFieldException e) {
            log.warn("未找到【code】属性");
        }
        return null;
    }

    public static <E extends Enum<E>> E codeOf(int code, Class<E> type) {
        E[] values = getValues(type);
        return getValue(values, code);
    }

    public static <E> E codeOf(int code, Type type) {
        E[] values = getValues(type);
        return getValue(values, code);
    }

    private static <E> E getValue(E[] values, int code) {
        if (values == null) {
            return null;
        }
        for (E value : values) {
            if (getCode(value) == code) {
                return value;
            }
        }
        return null;
    }


    private static <E extends Enum<E>> E[] getValues(Class<E> type) {
        return type.getEnumConstants();
    }

    private static <E> E[] getValues(Type type) {
        String typeName = type.getTypeName();

        Method method;
        try {
            Class<?> aClass = Class.forName(typeName);
            method = aClass.getMethod("values");
            method.setAccessible(true);
            return (E[]) method.invoke(aClass);
        } catch (NoSuchMethodException e) {
            log.warn("未找到【values】方法");
        } catch (IllegalAccessException e) {
            log.warn("没有权限执行【values】方法");
        } catch (InvocationTargetException e) {
            log.warn("【values】方法执行失败");
        } catch (ClassNotFoundException e) {
            log.warn("类【{}】未找到", typeName);
        }
        return null;
    }
}
